// 按值传递、按引用传递
// 从堆栈角度解释链表节点
// 以堆栈视角来看链表反转

#include <iostream>

using namespace std;

// 单链表节点
struct ListNode 
{
    int val;
    ListNode* next;

    ListNode(int val) : val(val), next(nullptr) {}
    ListNode(int val, ListNode* next) : val(val), next(next) {}
};

// 双链表节点
struct DoubleListNode 
{
    int value;
    DoubleListNode* last;
    DoubleListNode* next;

    DoubleListNode(int value) : value(value), last(nullptr), next(nullptr) {}
};

// 按值传递
void f(int a) 
{
    a = 0;
}

class Number 
{
public:
    int val;

    Number(int v) : val(v) {}
};

// 因为 b 仅仅是一个形参，修改形参并不会影响到真正的实参
void g1(Number* b) 
{
    b = nullptr;
}

// 修改了内存的数据，会影响到实参
void g2(Number* b)
{
    b->val = 6;
}

// 因为 c 仅仅是一个形参，修改形参并不会影响到真正的实参
void g3(int* c)
{
    c = nullptr;
}

// 修改了内存的数据，会影响到实参
void g4(int* c) 
{
    c[0] = 100;
}

// 反转单链表测试链接 : https://leetcode.cn/problems/reverse-linked-list/
class Solution 
{
public:
    ListNode* reverseList(ListNode* head) 
    {
        ListNode* pre = nullptr;
        ListNode* next = nullptr;
        // 头插法反转链表
        while (head != nullptr) 
        {
            next = head->next;
            head->next = pre;
            pre = head;
            head = next;
        }
        return pre;
    }
};

// 反转双链表
// 没有找到测试链接
// 如下方法是对的
DoubleListNode* reverseDoubleList(DoubleListNode* head) 
{
    DoubleListNode* pre = nullptr;
    DoubleListNode* next = nullptr;
    while (head != nullptr) 
    {
        next = head->next;
        head->next = pre;
        head->last = next;
        pre = head;
        head = next;
    }
    return pre;
}

int main() 
{
    // C++ 中有三种传参方式，分别是传值、传地址（指针）和传引用
    // 传指针和传引用一般来说都是能够实现相同的效果，也就是在函
    // 数内部修改参数会影响到外部的实参
    int a = 10;
    f(a);
    cout << a << endl; // 10

    Number* b = new Number(5);
    g1(b);
    cout << b->val << endl; // 5
    g2(b);
    cout << b->val << endl; // 6
    delete b;

    int* c = new int[4]{1, 2, 3, 4};
    g3(c);
    cout << c[0] << endl; // 1
    g4(c);
    cout << c[0] << endl; // 100
    delete[] c;

    return 0;
}